// Copyright 2021 by 马万里. All rights reserved.
// 开发团队 ：   鸡中之霸
// 开发人员 ：   马万里
// 开发时间 ：   2021/2/24 14:19
// 文件名称 ：   file.go
// 工程名称 ：   netpan
// 开发工具 ：   GoLand
//

package db

import (
	"database/sql"
	"fmt"
	myDB "johnsonsmile.cn/netpan/db/mysql"
)

// OnFileUploadFinished: 文件上传完成保存meta到mysql
func OnFileUploadFinished(filehash string, filename string, filesize int64, fileaddr string) bool {
	stmt, err := myDB.DBConn().Prepare(
		"INSERT IGNORE INTO tbl_file(`file_sha1`, `file_name`, `file_size`, `file_addr`, `status`) VALUES (?,?,?,?,1)",
	)
	if err != nil {
		fmt.Printf("Failed to prepare statement, err: %s\n", err.Error())
		return false
	}
	defer stmt.Close()
	ret, err := stmt.Exec(filehash, filename, filesize, fileaddr)
	if err != nil {
		fmt.Println(err.Error())
		return false
	}
	if rf, err := ret.RowsAffected(); nil == err {
		if rf <= 0 {
			fmt.Printf("File with hash: %s has been uploaded before\n", filehash)
		}
		return true
	}
	return false
}

// OnFileUpdateFinished: 更新文件信息到mysql
func OnFileUpdateFinished(filehash string, filename string) bool {
	stmt, err := myDB.DBConn().Prepare(
		"UPDATE tbl_file SET file_name = ? WHERE file_sha1 = ?",
	)
	if err != nil {
		fmt.Printf("Failed to prepare statement, err: %s\n", err.Error())
		return false
	}
	defer stmt.Close()
	ret, err := stmt.Exec(filename, filehash)
	if err != nil {
		fmt.Println(err.Error())
		return false
	}
	if rf, err := ret.RowsAffected(); nil == err {
		if rf <= 0 {
			fmt.Printf("File with hash: %s has not been uploaded before\n", filehash)
		}
		return true
	}
	return false
}

type TableFile struct {
	FileHash string
	FileName sql.NullString
	FileSize sql.NullInt64
	FileAddr sql.NullString
}

// GetFileMeta: 从mysql获取文件元信息
func GetFileMeta(filehash string) (*TableFile, error) {
	stmt, err := myDB.DBConn().Prepare(
		"SELECT file_sha1, file_addr,file_name, file_size FROM tbl_file WHERE file_sha1=? AND status=1 LIMIT 1",
	)
	if err != nil {
		fmt.Printf("Failed to prepare statement, err: %s\n", err.Error())
		return nil, err
	}
	defer stmt.Close()
	tfile := TableFile{}
	err = stmt.QueryRow(filehash).Scan(&tfile.FileHash, &tfile.FileAddr, &tfile.FileName, &tfile.FileSize)
	if err != nil {
		fmt.Printf("Failed to query file, err: %s\n", err.Error())
		return nil, err
	}
	return &tfile, nil
}

// GetFileMetaFileList: 从mysql中获取数据元信息的列表
func GetFileMetaFileList(limit int) ([]*TableFile, error) {
	stmt, err := myDB.DBConn().Prepare(
		"SELECT file_sha1, file_addr, file_name, file_size FROM tbl_file WHERE status = 1 LIMIT ?",
	)
	if err != nil {
		fmt.Printf("Failed to prepare statement, err: %s\n", err.Error())
		return nil, err
	}
	defer stmt.Close()

	rows, err := stmt.Query(limit)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	var tfiles []*TableFile = make([]*TableFile, 0)

	for rows.Next() {
		tfile := new(TableFile)
		err = rows.Scan(&tfile.FileHash, &tfile.FileAddr, &tfile.FileName, &tfile.FileSize)
		if err != nil {
			fmt.Println(err.Error())
			break
		}
		tfiles = append(tfiles, tfile)
	}
	return tfiles, nil
}

// OnFileRemoved: 文件删除(这里修改为status=2)
func OnFileRemoved(fileSha1 string) bool {
	stmt, err := myDB.DBConn().Prepare(
		"UPDATE tbl_file SET status = 2 WHERE file_sha1 = ? AND status = 1 LIMIT 1",
	)
	if err != nil {
		fmt.Printf("Failed to prepare statement, err: %s\n", err.Error())
		return false
	}
	defer stmt.Close()

	ret, err := stmt.Exec(fileSha1)
	if err != nil {
		fmt.Println(err.Error())
		return false
	}
	if rf, err := ret.RowsAffected(); nil == err {
		if rf <= 0 {
			fmt.Printf("File with hash: %s not uploaded\n", fileSha1)
		}
		return true
	}
	return false

}

// UpdateFileLocation : 更新文件的存储地址(如文件被转移了)
func UpdateFileLocation(filehash string, fileaddr string) bool {
	stmt, err := myDB.DBConn().Prepare(
		"update tbl_file set`file_addr`=? where  `file_sha1`=? limit 1")
	if err != nil {
		fmt.Println("预编译sql失败, err:" + err.Error())
		return false
	}
	defer stmt.Close()

	ret, err := stmt.Exec(fileaddr, filehash)
	if err != nil {
		fmt.Println(err.Error())
		return false
	}
	if rf, err := ret.RowsAffected(); nil == err {
		if rf <= 0 {
			fmt.Printf("更新文件location失败, filehash:%s", filehash)
		}
		return true
	}
	return false
}
